#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include "imu9250.h"

#define I2C_DEFAULT_TIMEOUT     1
#define I2C_DEFAULT_RETRY       3

int read_i2c(int dev_id, int slave_address, int reg_address);
int read_i2c_block_frequency(int dev_id, int slave_address, int reg_address, int frequency, unsigned char * data );
int write_i2c(int dev_id, int slave_address, int reg_address, int value);

int open_i2c(void)
{
	int dev_id;

	dev_id = open( I2C_DEV, O_RDWR );
	if (dev_id < 0) {
		perror("i2c open error.\n");
		exit(1);
	}

	return dev_id;
}

void close_i2c(int dev_id)
{
	close(dev_id);
}

int hd_i2c_set(int fd, unsigned int timeout, unsigned int retry)
{
    if (fd == 0 )
        return -1;

    if (ioctl(fd, I2C_TIMEOUT, timeout ? timeout : I2C_DEFAULT_TIMEOUT) < 0)
        return -1;

    if (ioctl(fd, I2C_RETRIES, retry ? retry : I2C_DEFAULT_RETRY) < 0)
        return -1;

    return 0;
}

/* i2c read and write */
int read_i2c(int dev_id, int slave_address, int reg_address)
{
	struct i2c_rdwr_ioctl_data iic_data;  
	int data = -1;
	int ret  = -1;

	iic_data.nmsgs = 2; 
    iic_data.msgs = (struct i2c_msg *)malloc(iic_data.nmsgs * sizeof(struct i2c_msg));  
    if (!iic_data.msgs){  
        printf("Memory alloc error\n");  
		free(iic_data.msgs);
        close(dev_id);  
        return -1;  
    }

	iic_data.nmsgs = 2;						// 读时序要两次过程，要发两次I2C消息  
    iic_data.msgs[0].len = 1;				// 信息长度为1，第一次只写要读的iic中存储单元的地址 
    iic_data.msgs[0].addr = slave_address;  
    iic_data.msgs[0].flags = 0;				// 写命令，看读时序理解 
	iic_data.msgs[0].buf = (unsigned char*)malloc(1); 
    iic_data.msgs[0].buf[0] = reg_address;	// 信息值  
          
    iic_data.msgs[1].len = 1;  
    iic_data.msgs[1].addr = slave_address;  
    iic_data.msgs[1].flags = I2C_M_RD;		// 读命令  
    iic_data.msgs[1].buf = (unsigned char*)malloc(1);  
    iic_data.msgs[1].buf[0] = 0;				// 先清空要读的缓冲区  

    ret = ioctl (dev_id, I2C_RDWR, (unsigned long)&iic_data);  
    if (ret < 0) {  
        printf ("ioctl read error\n"); 
		free(iic_data.msgs[0].buf);
		free(iic_data.msgs);
		return -1;
    }  
       
    //printf("read %02x from iic address %02x\n",iic_data.msgs[1].buf[0], reg_address);  
	data = iic_data.msgs[1].buf[0];

	free(iic_data.msgs[0].buf);
	free(iic_data.msgs);

	return data;
}

int read_i2c_block_frequency(int dev_id, int slave_address, int reg_address, int frequency, unsigned char * data )
{
	int i;

	for (i = 0; i < frequency; i++) {
		data[i] = read_i2c(dev_id, slave_address, reg_address + i);
	}

	return 0;
}

int write_i2c(int dev_id, int slave_address, int reg_address, int value)
{
	struct i2c_rdwr_ioctl_data iic_data;
	int ret  = -1;

    iic_data.nmsgs = 2;
    iic_data.msgs = (struct i2c_msg *)malloc(iic_data.nmsgs * sizeof(struct i2c_msg));  
    if (!iic_data.msgs){  
        printf("Memory alloc error\n");  
        close(dev_id);  
		free(iic_data.msgs);
        return -1;  
    } 

	ioctl(dev_id, I2C_TIMEOUT, 2);//设置超时时间  
    ioctl(dev_id, I2C_RETRIES, 1);//设置重发次数  
	
	iic_data.nmsgs = 1;  
    iic_data.msgs[0].len = 2;				// 信息长度为2，看写时序，iic的地址不算的，因为付给了addr，而len是指buf中的值的个数  
    iic_data.msgs[0].addr = slave_address;  
    iic_data.msgs[0].flags = 0;				// 写命令  
    iic_data.msgs[0].buf = (unsigned char*)malloc(2);  
    iic_data.msgs[0].buf[0] = reg_address;	// 信息值1 iic中存储单元的地址，即你要往哪写  
    iic_data.msgs[0].buf[1] = value;			// 信息值2,即你要写什么  
      
    ret = ioctl (dev_id, I2C_RDWR, (unsigned long)&iic_data);
    if (ret < 0) {  
        printf ("ioctl write error\n");
		free(iic_data.msgs[0].buf);
		free(iic_data.msgs);
		return -1;
    }  
	
	free(iic_data.msgs[0].buf);
	free(iic_data.msgs);
	
	return 0;
}


int main()
{
	int dev;
	unsigned char data = 0;
	unsigned char array[3] = {0};

	dev = open_i2c();

	hd_i2c_set(dev, 2,2);

	/* 7bit addrs  */
	if (ioctl(dev, I2C_TENBIT, 0) != 0) {
		perror("I2C_TENBIT set was fail.\n");
		return -1;
	}

	/* i2c slave address */
	if (ioctl(dev, I2C_SLAVE, SLAVE_ADDR) != 0) {
		perror("I2C_SLAVE set was fail.\n");
		return -1;
	}
	
	data = read_i2c(dev, 0x68, 0x75);
	printf("data = 0x%02x\n", data);

	read_i2c_block_frequency(dev, 0x68, 0x00, 3, array);
	printf("array = 0x%02x 0x%02x 0x%02x\n", array[0], array[1], array[2]);

	write_i2c(dev, 0x68, 0x00, 0xee);
	write_i2c(dev, 0x68, 0x01, 0xdd);
	write_i2c(dev, 0x68, 0x02, 0xaa);

	read_i2c_block_frequency(dev, 0x68, 0x00, 3, array);
	printf("array = 0x%02x 0x%02x 0x%02x\n", array[0], array[1], array[2]);

	return 0;
}




